﻿using Abp.Application.Services.Dto;
using Abp.Domain.Repositories;
using Abp.UI;
using System.Linq;
using Abp.Linq.Extensions;
using Camc.Quality.Authorization.Users;
using Camc.Quality.CodeFormat;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Reflection;
using System.Threading.Tasks;
using Camc.Quality.IOperationHistory;
using Camc.Quality.Common;

namespace Camc.Quality.SystemManagement
{
    public class CodeFormatDescAppService : QualityAppServiceBase
    {
        private readonly IRepository<CodeFormatDesc, Guid> _codeFormatDescRepository;
        private readonly IRepository<CodeFormatRuleDesc, Guid> _codeFormatRuleDescRepository;
        private readonly IRepository<CodeFormatSerialInfo, Guid> _codeFormatSerialInfoRepository;
        private readonly IRepository<CodeFormatRecord, Guid> _codeFormatRecordRepository;
        private readonly IRepository<User, long> _userRepository;
        private readonly IOperationHistoryAppService _iOperationHistoryAppService;
        public CodeFormatDescAppService(IRepository<CodeFormatDesc, Guid> codeFormatDescRepository,
                                 IRepository<CodeFormatRuleDesc, Guid> codeFormatRuleDescRepository,
                                 IRepository<CodeFormatSerialInfo, Guid> codeFormatSerialInfoRepository,
                                 IRepository<CodeFormatRecord, Guid> codeFormatRecordRepository,
                                 IRepository<User, long> userRepository,
                                 IOperationHistoryAppService iOperationHistoryAppService
                                 )
        {
            _codeFormatDescRepository = codeFormatDescRepository;
            _codeFormatRuleDescRepository = codeFormatRuleDescRepository;
            _codeFormatSerialInfoRepository = codeFormatSerialInfoRepository;
            _codeFormatRecordRepository = codeFormatRecordRepository;
            _userRepository = userRepository;
            _iOperationHistoryAppService = iOperationHistoryAppService;
        }
        /// <summary>
        /// 编码规则查询
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<PagedResultDto<CodeFormatDto>> GetCodeFormatList(GetCodeFormatListInput input)
        {
            //查询CodeFormatDesc表
            var codeFormatDescList = _codeFormatDescRepository.GetAll();
            IList<CodeFormatDto> codeFormatDtos = new List<CodeFormatDto>();
            if (!string.IsNullOrEmpty(input.CodeNameStr))
            {
                codeFormatDescList = codeFormatDescList.Where(d => d.CodeName.Contains(input.CodeNameStr));
             }
            if (input.IsUsed != null)
            {
                codeFormatDescList = codeFormatDescList.Where(d => d.IsUsed == (CodeFormat.IsUsed)input.IsUsed);
            }
            var count = codeFormatDescList.Count();
            codeFormatDescList = codeFormatDescList.OrderByDescending(e => e.LastModificationTime).PageBy(input);
            foreach (var item in codeFormatDescList)
            {
                long? userId = null;
                if (item.LastModifierUserId != null)
                {
                    userId = item.LastModifierUserId;
                }
                else
                {
                    userId = item.CreatorUserId;
                }
                var users = _userRepository.FirstOrDefaultAsync(p => p.Id == userId).Result;
                DateTime lastModificationTime = new DateTime();
                if (item.LastModificationTime == null)
                {
                    lastModificationTime = (DateTime)item.CreationTime;
                }
                else
                {
                    lastModificationTime = (DateTime)item.LastModificationTime;
                }
                var codeFormatDtoList = new CodeFormatDto()
                {
                    Id = item.Id,
                    CodeName = item.CodeName,
                    SysRules = item.SysRules,
                    AutoGenerate = (int)item.AutoGenerate,
                    IsUsed = (int)item.IsUsed,
                    Remark = item.Remark,
                    UserName = users.Surname + users.Name, 
                    LastModificationTime = lastModificationTime,
                    AvailableModules = item.AvailableModules

                };
                codeFormatDtos.Add(codeFormatDtoList);
            }
            var Result = ObjectMapper.Map<List<CodeFormatDto>>(codeFormatDtos);

                foreach (CodeFormatDto cf in Result)
                {
                    //查询CodeFormatRuleDesc表
                    var codeFormatRuleList = _codeFormatRuleDescRepository.GetAll().Where(a => a.CodeFormatId == cf.Id).OrderByDescending(e => e.RuleSort);
                    //查询CodeFormatSerialInfo表
                    var codeFormatSerialInfoList = await _codeFormatSerialInfoRepository.FirstOrDefaultAsync(a => a.CodeFormatId == cf.Id);
                    IList<CodeFormatRuleDto> codeFormatRuleDtos = new List<CodeFormatRuleDto>();
                    foreach (CodeFormatRuleDesc codeFormatRuleDesc in codeFormatRuleList)
                    {
                        CodeFormatRuleDto codeFormatRuleDto = new CodeFormatRuleDto
                        {
                            CodeFormatId = codeFormatRuleDesc.CodeFormatId,
                            RuleKey = (int)codeFormatRuleDesc.RuleKey,
                            RuleValue = codeFormatRuleDesc.RuleValue,
                            RuleSort = int.Parse(codeFormatRuleDesc.RuleSort),
                            SerialLength = codeFormatSerialInfoList.SerialLength,
                            Encoding = codeFormatSerialInfoList.Encoding,
                            StartNum = codeFormatSerialInfoList.StartNum,
                            Step = codeFormatSerialInfoList.Step
                        };
                        codeFormatRuleDtos.Add(codeFormatRuleDto);
                    }
                    cf.CodeFormatRuleDto = codeFormatRuleDtos;
                }
                //var count = Result.Count();
                return new PagedResultDto<CodeFormatDto>(count, Result);
        }
        public static string GetEnumDesc(Enum e)
        {
            FieldInfo EnumInfo = e.GetType().GetField(e.ToString());
            if (EnumInfo == null)
            {
                return "";
            }
            DescriptionAttribute[] EnumAttributes
                = (DescriptionAttribute[])EnumInfo.GetCustomAttributes(typeof(DescriptionAttribute), false);
            if (EnumAttributes.Length > 0)
            {
                return EnumAttributes[0].Description;
            }
            return e.ToString();
        }
        /// <summary>
        /// 删除编码规则
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<ResultMessage> DeleteCodeFormat(List<CodeFormatDeleteDto> input)
        {
            ResultMessage resultMessage = new ResultMessage();
            try
            {
                foreach (var item in input)
                {
                    var count = await _codeFormatDescRepository.CountAsync(p => p.Id == item.Id);
                    if (count == 0)
                    {
                        resultMessage.code = 1;
                        resultMessage.Message = "删除失败！";
                        return resultMessage;
                    }
                    else
                    {
                        //根据Guid删除CodeFormatDesc数据
                        await _codeFormatDescRepository.DeleteAsync(p => p.Id == item.Id);

                        //删除CodeFormatSerialInfo数据
                        await _codeFormatSerialInfoRepository.DeleteAsync(p => p.CodeFormatId == item.Id);
                        //删除CodeFormatRuleDesc数据
                        await _codeFormatRuleDescRepository.DeleteAsync(p => p.CodeFormatId == item.Id);
                    }
                } 
                resultMessage.code = 0;
                return resultMessage;
            }
            catch (Exception ex)
            {
                resultMessage.code = 1;
                resultMessage.Message = ex.Message;
                return resultMessage;
            }
        }
        /// <summary>
        /// 启用停用接口
        /// </summary>
        /// <param name="input"></param>
        /// <param name="isUsed"></param>
        /// <returns></returns>
        public async Task EnableOrDisableUpdate(List<CodeFormatEnableDto> input, int isUsed)
        {
            foreach (var item in input)
            {
                var codeFormat = await _codeFormatDescRepository.FirstOrDefaultAsync(a => a.Id == item.Id);
                codeFormat.IsUsed = (CodeFormat.IsUsed)isUsed;
                await _codeFormatDescRepository.UpdateAsync(codeFormat);
                //记录操作履历
                if (codeFormat.IsUsed == CodeFormat.IsUsed.启用)
                {
                    _iOperationHistoryAppService.InsertOperationLog(codeFormat.Id, 5, 15, "启用编码规则");
                    //await CreatCodeFromatRecord(codeFormat.Id, 2, null);
                }
                if (codeFormat.IsUsed == CodeFormat.IsUsed.不启用)
                {
                    _iOperationHistoryAppService.InsertOperationLog(codeFormat.Id, 5, 15, "停用编码规则" );
                    //await CreatCodeFromatRecord(codeFormat.Id, 3, null);
                }
            }
        }
        /// <summary>
        /// 编码规则表新增和修改接口，根据是否传输id判断
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<ResultMessage> CreateOrUpdateCodeFormat(CodeFormatDto input)
        {
            ResultMessage resultMessage = new ResultMessage();
            if (input.Id == Guid.Empty)
            {
                resultMessage = await CreateCodeFormat(input);
            }
            else
            {
                resultMessage = await UpdateCodeFormat(input);
            }
            return resultMessage;
        }
        /// <summary>
        /// 编码规则表insert
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        private async Task<ResultMessage> CreateCodeFormat(CodeFormatDto input)
        {
            ResultMessage resultMessage = new ResultMessage();
            try
            {
                var availableModules = _codeFormatDescRepository.GetAll().Where(s => s.AvailableModules == input.AvailableModules && s.IsUsed == IsUsed.启用);
                if (availableModules.Count() > 0)
                {
                    resultMessage.code = 1;
                    resultMessage.Message = "一个模块只能绑定一个编码规则";
                    return resultMessage;
                    //throw new UserFriendlyException("一个模块只能绑定一个编码规则");
                }
                if (input.CodeName.Trim() == "")
                {
                    resultMessage.code = 1;
                    resultMessage.Message = "编码名称不能为空";
                    return resultMessage;
                    //throw new UserFriendlyException("编码名称不能为空");
                }
                var rulesList = input.CodeFormatRuleDto;
                // 规则类型0：常量、1：日期格式、2：流水号
                var serialNumber = rulesList.Where(a => a.RuleKey == 2);
                var constantList = rulesList.Where(a => a.RuleKey == 0);
                var date = rulesList.FirstOrDefault(a => a.RuleKey == 1);
                if (serialNumber.Count() == 0)
                {
                    resultMessage.code = 1;
                    resultMessage.Message = "必须有流水号";
                    return resultMessage;
                    //throw new UserFriendlyException("必须有流水号");
                }
                //系统规则=常量+日期+流水码(长度*起始值)
                var sysRules = "";
                foreach (var item in constantList)
                {
                    if (string.IsNullOrEmpty(item.RuleValue))
                    {
                        resultMessage.code = 1;
                        resultMessage.Message = "请完善编码规则";
                        return resultMessage;
                        //throw new UserFriendlyException("请完善编码规则");
                    }
                    else
                    {
                        sysRules = sysRules + item.RuleValue.ToString();
                    }
                }
                foreach (var item in serialNumber)
                {
                    if (string.IsNullOrEmpty(item.SerialLength) || string.IsNullOrEmpty(item.Step) || string.IsNullOrEmpty(item.StartNum))
                    {
                        resultMessage.code = 1;
                        resultMessage.Message = "请完善编码规则";
                        return resultMessage;
                        //throw new UserFriendlyException("请完善编码规则");
                    }
                    else
                    {
                        sysRules = sysRules + date.RuleValue + item.StartNum.ToString().PadLeft(Convert.ToInt32(item.SerialLength), '0');
                    }
                }
                //CodeFormatDesc表insert
                var codeFormat = new CodeFormatDesc()
                {
                    Id = Guid.NewGuid(),
                    CodeName = input.CodeName,
                    SysRules = sysRules,
                    //AutoGenerate = (AutoGenerates)Enum.Parse(typeof(AutoGenerates),input.AutoGenerate.ToString()),
                    AutoGenerate = (AutoGenerates)input.AutoGenerate,
                    IsUsed = (CodeFormat.IsUsed)input.IsUsed,
                    Remark = input.Remark,
                    LastModificationTime = input.CreationTime,
                    AvailableModules = input.AvailableModules
                };
                _codeFormatDescRepository.Insert(codeFormat);
                //记录操作履历
                _iOperationHistoryAppService.InsertOperationLog(codeFormat.Id, 5, 14, "新增编码规则：" + sysRules);
                //await CreatCodeFromatRecord(codeFormat.Id, 0, sysRules);
                //CodeFormatSerialInfo表insert
                foreach (var item in input.CodeFormatRuleDto)
                {
                    if (string.IsNullOrEmpty(item.RuleValue))
                    {
                        resultMessage.code = 1;
                        resultMessage.Message = "请完善编码规则";
                        return resultMessage;
                        //throw new UserFriendlyException("请完善编码规则");
                    }
                    else
                    {
                        var codeFormatRuleDesc = new CodeFormatRuleDesc()
                        {
                            Id = Guid.NewGuid(),
                            CodeFormatId = codeFormat.Id,
                            RuleKey = (RuleKey)item.RuleKey,
                            RuleValue = item.RuleValue,
                            RuleSort = Convert.ToString(item.RuleSort),
                        };
                        await _codeFormatRuleDescRepository.InsertAsync(codeFormatRuleDesc);
                        //CodeFormatRuleDesc表insert
                        if (item.RuleKey == 2)
                        {
                            if (string.IsNullOrEmpty(item.SerialLength) || string.IsNullOrEmpty(item.Step) || string.IsNullOrEmpty(item.StartNum))
                            {
                                resultMessage.code = 1;
                                resultMessage.Message = "请完善编码规则";
                                return resultMessage;
                                //throw new UserFriendlyException("请完善编码规则");
                            }
                            else
                            {
                                var codeFormatSerialInfo = new CodeFormatSerialInfo()
                                {
                                    Id = Guid.NewGuid(),
                                    CodeFormatId = codeFormat.Id,
                                    SerialLength = item.SerialLength,
                                    Encoding = item.Encoding,
                                    StartNum = item.StartNum,
                                    Step = item.Step,
                                };
                                await _codeFormatSerialInfoRepository.InsertAsync(codeFormatSerialInfo);
                            }
                        }
                    }
                }
                resultMessage.code = 0;
                return resultMessage;
            }
            catch (Exception ex)
            {
                resultMessage.code = 1;
                resultMessage.Message = ex.Message;
                return resultMessage;
            }

        }
        /// <summary>
        /// 编码规则表update
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        private async Task<ResultMessage> UpdateCodeFormat(CodeFormatDto input)
        {
            ResultMessage resultMessage = new ResultMessage();
            try
            {
                var availableModules = _codeFormatDescRepository.FirstOrDefault(s => s.AvailableModules == input.AvailableModules && s.IsUsed == IsUsed.启用);
                if (availableModules != null && input.Id != availableModules.Id)
                {
                    resultMessage.code = 1;
                    resultMessage.Message = "一个模块只能绑定一个编码规则";
                    return resultMessage;
                    //throw new UserFriendlyException("一个模块只能绑定一个编码规则");
                }
                if (input.CodeName.Trim() == "")
                {
                    resultMessage.code = 1;
                    resultMessage.Message = "编码名称不能为空";
                    return resultMessage;
                    //throw new UserFriendlyException("编码名称不能为空");
                }
                if (input.CodeName.Trim() == "")
                {
                    resultMessage.code = 1;
                    resultMessage.Message = "编码名称不能为空";
                    return resultMessage;
                    //throw new UserFriendlyException("编码名称不能为空");
                }
                var rulesList = input.CodeFormatRuleDto;
                // 规则类型0：常量、1：日期格式、2：流水号
                var serialNumber = rulesList.Where(a => a.RuleKey == 2);
                var constantList = rulesList.Where(a => a.RuleKey == 0);
                var date = rulesList.FirstOrDefault(a => a.RuleKey == 1);
                if (serialNumber.Count() == 0)
                {
                    resultMessage.code = 1;
                    resultMessage.Message = "必须有流水号";
                    return resultMessage;
                    //throw new UserFriendlyException("必须有流水号");
                }
                //系统规则=常量+日期+流水码(长度*起始值)
                var sysRules = "";
                foreach (var item in constantList)
                {
                    if (string.IsNullOrEmpty(item.RuleValue))
                    {
                        resultMessage.code = 1;
                        resultMessage.Message = "请完善编码规则";
                        return resultMessage;
                        //throw new UserFriendlyException("请完善编码规则");
                    }
                    else
                    {
                        sysRules = sysRules + item.RuleValue.ToString();
                    }
                }
                foreach (var item in serialNumber)
                {
                    if (string.IsNullOrEmpty(item.SerialLength) || string.IsNullOrEmpty(item.Step) || string.IsNullOrEmpty(item.StartNum))
                    {
                        resultMessage.code = 1;
                        resultMessage.Message = "请完善编码规则";
                        return resultMessage;
                        //throw new UserFriendlyException("请完善编码规则");
                    }
                    else
                    {
                        sysRules = sysRules + date.RuleValue + item.StartNum.ToString().PadLeft(Convert.ToInt32(item.SerialLength), '0');
                    }
                }
                //CodeFormatDesc表update
                var codeFormat = await _codeFormatDescRepository.FirstOrDefaultAsync(c => c.Id == input.Id);
                if (codeFormat != null)
                {
                    codeFormat.CodeName = input.CodeName;
                    codeFormat.SysRules = sysRules;
                    codeFormat.AutoGenerate = (AutoGenerates)input.AutoGenerate;
                    codeFormat.IsUsed = (CodeFormat.IsUsed)input.IsUsed;
                    codeFormat.Remark = input.Remark;
                    codeFormat.AvailableModules = input.AvailableModules;
                    await _codeFormatDescRepository.UpdateAsync(codeFormat);
                    //记录操作履历
                    _iOperationHistoryAppService.InsertOperationLog(codeFormat.Id, 5, 15, "修改编码规则：" + sysRules);
                    //await CreatCodeFromatRecord(codeFormat.Id, 1, sysRules);
                    var count = _codeFormatRuleDescRepository.GetAll().Where(p => p.CodeFormatId == input.Id).Count();
                    //删除现有规则重新insert
                    if (count != 0)
                    {
                        //根据CodeFormatID删除CodeFormatRuleDesc表相关数据
                        await _codeFormatRuleDescRepository.DeleteAsync(p => p.CodeFormatId == input.Id);
                    }
                    foreach (var item in input.CodeFormatRuleDto)
                    {
                        if (string.IsNullOrEmpty(item.RuleValue))
                        {
                            resultMessage.code = 1;
                            resultMessage.Message = "请完善编码规则";
                            return resultMessage;
                            //throw new UserFriendlyException("请完善编码规则");
                        }
                        else
                        {
                            var codeFormatRuleDesc = new CodeFormatRuleDesc()
                            {
                                Id = Guid.NewGuid(),
                                CodeFormatId = input.Id,
                                RuleKey = (RuleKey)item.RuleKey,
                                RuleValue = item.RuleValue,
                                RuleSort = Convert.ToString(item.RuleSort),
                            };
                            await _codeFormatRuleDescRepository.InsertAsync(codeFormatRuleDesc);
                            //CodeFormatSerialInfo表update
                            if (item.RuleKey == 2)
                            {
                                if (string.IsNullOrEmpty(item.SerialLength) || string.IsNullOrEmpty(item.Step) || string.IsNullOrEmpty(item.StartNum))
                                {
                                    resultMessage.code = 1;
                                    resultMessage.Message = "请完善编码规则";
                                    return resultMessage;
                                    //throw new UserFriendlyException("请完善编码规则");
                                }
                                else
                                {
                                    var codeFormatSerialInfo = await _codeFormatSerialInfoRepository.FirstOrDefaultAsync(c => c.CodeFormatId == input.Id);
                                    {
                                        codeFormatSerialInfo.SerialLength = item.SerialLength;
                                        codeFormatSerialInfo.Encoding = item.Encoding;
                                        codeFormatSerialInfo.StartNum = item.StartNum;
                                        codeFormatSerialInfo.Step = item.Step;
                                    };
                                    await _codeFormatSerialInfoRepository.UpdateAsync(codeFormatSerialInfo);
                                }
                            }
                        }
                    }
                }
                resultMessage.code = 0;
                return resultMessage;
            }
            catch (Exception ex)
            {
                resultMessage.code = 1;
                resultMessage.Message = ex.Message;
                return resultMessage;
            }
        }
        /// <summary>
        /// 根据编码规则获取订单号
        /// </summary>
        /// <param name="availableModules"></param>
        /// <returns></returns>
        public string GetCodeFormat(string availableModules)
        {
            var codeFormat = _codeFormatDescRepository.FirstOrDefault(a=>a.AvailableModules == availableModules && a.IsUsed == IsUsed.启用);
            if (codeFormat != null)
            {
                var rulesList = _codeFormatRuleDescRepository.GetAll().Where(a => a.CodeFormatId == codeFormat.Id);
                var serialNumber = _codeFormatSerialInfoRepository.FirstOrDefault(a => a.CodeFormatId == codeFormat.Id);
                var constantList = rulesList.Where(a => a.RuleKey == RuleKey.常量);
                var date = rulesList.FirstOrDefault(a => a.RuleKey == RuleKey.日期格式);
                var sysRules = "";
                foreach (var item in constantList)
                {
                    sysRules = sysRules + item.RuleValue.ToString();
                }
                var codeRedord = _codeFormatRecordRepository.GetAll().OrderByDescending(d => d.CreationTime).FirstOrDefault(d => d.CodeFormatId == codeFormat.Id && d.CreationTime.ToString("d") == DateTime.Today.ToString("d"));
                int serialCode = 0;
                if (codeRedord != null)
                {
                    serialCode = Convert.ToInt32(codeRedord.Code.Substring(codeRedord.Code.Length - (Convert.ToInt32(serialNumber.SerialLength)))) + Convert.ToInt32(serialNumber.Step);
                }
                else
                {
                    serialCode = Convert.ToInt32(serialNumber.StartNum);
                }
                var code = sysRules + DateTime.Now.ToString(date.RuleValue) + serialCode.ToString().PadLeft(Convert.ToInt32(serialNumber.SerialLength), '0');
                var codeFormatRecord = new CodeFormatRecord()
                {
                    Id = Guid.NewGuid(),
                    CodeFormatId = codeFormat.Id,
                    Code = code
                };
                _codeFormatRecordRepository.InsertAsync(codeFormatRecord);
                return code;
            }
            else 
            {
                return null;
            }
        }
        /// <summary>
        /// 编码规则下拉列表
        /// </summary>
        /// <returns></returns>
        public List<CodeFormatDto> GetCodeFormatDropList()
        {
            var codeFormatDescList = _codeFormatDescRepository.GetAll().Where(d=>d.IsUsed == CodeFormat.IsUsed.启用);
            var Result = ObjectMapper.Map<List<CodeFormatDto>>(codeFormatDescList);
            return Result;
        }
        /// <summary>
        /// 编码规则生成订单号
        /// </summary>
        /// <param name="sysRules">常量</param>
        /// <param name="dateRule">日期（yyyyMMdd,yyMMdd,yyyyMM,yymm,MMdd,yy,MM）</param>
        /// <param name="startNum">起始值</param>
        /// <param name="serialLength">长度</param>
        /// <param name="step">步长</param>
        /// <returns></returns>
        public string GetOrderCode(string sysRules, string dateRule, int startNum, int serialLength, int step)
        {
            var code = sysRules + DateTime.Now.ToString(dateRule);// + startNum.ToString().PadLeft(serialLength, '0');
            var codeRedord = _codeFormatRecordRepository.GetAll().OrderByDescending(d => d.CreationTime).FirstOrDefault(d => d.Code.Substring(0, d.Code.Length - serialLength) == code && d.CreationTime.ToString("d") == DateTime.Today.ToString("d"));
            int serialCode = 0;
            if (codeRedord != null)
            {
                serialCode = Convert.ToInt32(codeRedord.Code.Substring(codeRedord.Code.Length - (Convert.ToInt32(serialLength)))) + Convert.ToInt32(step);
            }
            else
            {
                serialCode = startNum;
            }
            code = sysRules + DateTime.Now.ToString(dateRule) + serialCode.ToString().PadLeft(serialLength, '0');
            var codeFormatRecord = new CodeFormatRecord()
            {
                Id = Guid.NewGuid(),
                CodeFormatId = Guid.Empty,
                Code = code
            };
            _codeFormatRecordRepository.InsertAsync(codeFormatRecord);
            return code;
        }
    }
}
